package com.cencat.order.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import jakarta.validation.constraints.*;
import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 线路发票数据传输对象
 * 
 * @author cencat
 * @date 2024-01-20
 */
@Data
@Accessors(chain = true)
public class RouteInvoiceDTO implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 发票ID(更新时必填)
     */
    private Long invoiceId;

    /**
     * 发票编号
     */
    @Size(max = 50, message = "发票编号长度不能超过50个字符")
    private String invoiceCode;

    /**
     * 发票类型(1-普通发票 2-专用发票 3-电子发票)
     */
    @NotNull(message = "发票类型不能为空")
    @Min(value = 1, message = "发票类型值不正确")
    @Max(value = 3, message = "发票类型值不正确")
    private Integer invoiceType;

    /**
     * 发票状态(0-草稿 1-待审核 2-已审核 3-已开票 4-已作废 5-已红冲)
     */
    @Min(value = 0, message = "发票状态值不正确")
    @Max(value = 5, message = "发票状态值不正确")
    private Integer invoiceStatus;

    /**
     * 路线ID
     */
    private Long routeId;

    /**
     * 路线编号
     */
    @Size(max = 50, message = "路线编号长度不能超过50个字符")
    private String routeCode;

    /**
     * 路线名称
     */
    @Size(max = 100, message = "路线名称长度不能超过100个字符")
    private String routeName;

    /**
     * 商家ID
     */
    private Long merchantId;

    /**
     * 商家编号
     */
    @Size(max = 50, message = "商家编号长度不能超过50个字符")
    private String merchantCode;

    /**
     * 商家名称
     */
    @Size(max = 100, message = "商家名称长度不能超过100个字符")
    private String merchantName;

    /**
     * 开票日期
     */
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate invoiceDate;

    /**
     * 开票期间(格式：YYYY-MM)
     */
    @Size(max = 10, message = "开票期间长度不能超过10个字符")
    private String invoicePeriod;

    /**
     * 统计开始日期
     */
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate statisticsStartDate;

    /**
     * 统计结束日期
     */
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate statisticsEndDate;

    /**
     * 购买方名称
     */
    @NotBlank(message = "购买方名称不能为空")
    @Size(max = 100, message = "购买方名称长度不能超过100个字符")
    private String buyerName;

    /**
     * 购买方税号
     */
    @Size(max = 50, message = "购买方税号长度不能超过50个字符")
    private String buyerTaxNumber;

    /**
     * 购买方地址
     */
    @Size(max = 200, message = "购买方地址长度不能超过200个字符")
    private String buyerAddress;

    /**
     * 购买方电话
     */
    @Size(max = 20, message = "购买方电话长度不能超过20个字符")
    private String buyerPhone;

    /**
     * 购买方开户行
     */
    @Size(max = 100, message = "购买方开户行长度不能超过100个字符")
    private String buyerBank;

    /**
     * 购买方账号
     */
    @Size(max = 50, message = "购买方账号长度不能超过50个字符")
    private String buyerAccount;

    /**
     * 销售方名称
     */
    @NotBlank(message = "销售方名称不能为空")
    @Size(max = 100, message = "销售方名称长度不能超过100个字符")
    private String sellerName;

    /**
     * 销售方税号
     */
    @Size(max = 50, message = "销售方税号长度不能超过50个字符")
    private String sellerTaxNumber;

    /**
     * 销售方地址
     */
    @Size(max = 200, message = "销售方地址长度不能超过200个字符")
    private String sellerAddress;

    /**
     * 销售方电话
     */
    @Size(max = 20, message = "销售方电话长度不能超过20个字符")
    private String sellerPhone;

    /**
     * 销售方开户行
     */
    @Size(max = 100, message = "销售方开户行长度不能超过100个字符")
    private String sellerBank;

    /**
     * 销售方账号
     */
    @Size(max = 50, message = "销售方账号长度不能超过50个字符")
    private String sellerAccount;

    /**
     * 货物或应税劳务名称
     */
    @NotBlank(message = "货物或应税劳务名称不能为空")
    @Size(max = 200, message = "货物或应税劳务名称长度不能超过200个字符")
    private String goodsName;

    /**
     * 规格型号
     */
    @Size(max = 100, message = "规格型号长度不能超过100个字符")
    private String specification;

    /**
     * 单位
     */
    @Size(max = 20, message = "单位长度不能超过20个字符")
    private String unit;

    /**
     * 数量
     */
    @DecimalMin(value = "0.01", message = "数量不能小于0.01")
    private BigDecimal quantity;

    /**
     * 单价
     */
    @DecimalMin(value = "0.01", message = "单价不能小于0.01")
    private BigDecimal unitPrice;

    /**
     * 金额(不含税)
     */
    @DecimalMin(value = "0.01", message = "金额不能小于0.01")
    private BigDecimal amount;

    /**
     * 税率(%)
     */
    @DecimalMin(value = "0.0", message = "税率不能小于0%")
    @DecimalMax(value = "100.0", message = "税率不能大于100%")
    private BigDecimal taxRate;

    /**
     * 税额
     */
    @DecimalMin(value = "0.0", message = "税额不能小于0")
    private BigDecimal taxAmount;

    /**
     * 价税合计
     */
    @DecimalMin(value = "0.01", message = "价税合计不能小于0.01")
    private BigDecimal totalAmount;

    /**
     * 合计金额(不含税)
     */
    @DecimalMin(value = "0.01", message = "合计金额不能小于0.01")
    private BigDecimal totalAmountExcludingTax;

    /**
     * 合计税额
     */
    @DecimalMin(value = "0.0", message = "合计税额不能小于0")
    private BigDecimal totalTaxAmount;

    /**
     * 价税合计(大写)
     */
    @Size(max = 200, message = "价税合计大写长度不能超过200个字符")
    private String totalAmountInWords;

    /**
     * 收款人
     */
    @Size(max = 50, message = "收款人长度不能超过50个字符")
    private String payee;

    /**
     * 复核
     */
    @Size(max = 50, message = "复核长度不能超过50个字符")
    private String reviewer;

    /**
     * 开票人
     */
    @Size(max = 50, message = "开票人长度不能超过50个字符")
    private String drawer;

    /**
     * 发票号码
     */
    @Size(max = 50, message = "发票号码长度不能超过50个字符")
    private String invoiceNumber;

    /**
     * 发票代码
     */
    @Size(max = 50, message = "发票代码长度不能超过50个字符")
    private String invoiceCodeNumber;

    /**
     * 机器编号
     */
    @Size(max = 50, message = "机器编号长度不能超过50个字符")
    private String machineNumber;

    /**
     * 密码区
     */
    @Size(max = 500, message = "密码区长度不能超过500个字符")
    private String passwordArea;

    /**
     * 备注
     */
    @Size(max = 500, message = "备注长度不能超过500个字符")
    private String remark;

    /**
     * 审核状态(0-未审核 1-审核中 2-审核通过 3-审核拒绝)
     */
    @Min(value = 0, message = "审核状态值不正确")
    @Max(value = 3, message = "审核状态值不正确")
    private Integer auditStatus;

    /**
     * 审核人ID
     */
    private Long auditorId;

    /**
     * 审核人姓名
     */
    @Size(max = 50, message = "审核人姓名长度不能超过50个字符")
    private String auditorName;

    /**
     * 审核时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime auditTime;

    /**
     * 审核意见
     */
    @Size(max = 500, message = "审核意见长度不能超过500个字符")
    private String auditOpinion;

    /**
     * 打印次数
     */
    @Min(value = 0, message = "打印次数不能小于0")
    private Integer printCount;

    /**
     * 最后打印时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime lastPrintTime;

    /**
     * 打印人ID
     */
    private Long printerId;

    /**
     * 打印人姓名
     */
    @Size(max = 50, message = "打印人姓名长度不能超过50个字符")
    private String printerName;

    /**
     * 发票模板ID
     */
    private Long templateId;

    /**
     * 发票模板名称
     */
    @Size(max = 100, message = "发票模板名称长度不能超过100个字符")
    private String templateName;

    /**
     * 生成方式(1-手动生成 2-自动生成 3-批量生成)
     */
    @Min(value = 1, message = "生成方式值不正确")
    @Max(value = 3, message = "生成方式值不正确")
    private Integer generateMethod;

    /**
     * 生成时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime generateTime;

    /**
     * 生成人ID
     */
    private Long generatorId;

    /**
     * 生成人姓名
     */
    @Size(max = 50, message = "生成人姓名长度不能超过50个字符")
    private String generatorName;

    /**
     * 作废原因
     */
    @Size(max = 500, message = "作废原因长度不能超过500个字符")
    private String voidReason;

    /**
     * 作废时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime voidTime;

    /**
     * 作废人ID
     */
    private Long voiderId;

    /**
     * 作废人姓名
     */
    @Size(max = 50, message = "作废人姓名长度不能超过50个字符")
    private String voiderName;

    /**
     * 红冲原因
     */
    @Size(max = 500, message = "红冲原因长度不能超过500个字符")
    private String redRushReason;

    /**
     * 红冲时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime redRushTime;

    /**
     * 红冲人ID
     */
    private Long redRusherId;

    /**
     * 红冲人姓名
     */
    @Size(max = 50, message = "红冲人姓名长度不能超过50个字符")
    private String redRusherName;

    /**
     * 原发票ID(红冲发票关联的原发票)
     */
    private Long originalInvoiceId;

    /**
     * 原发票编号
     */
    @Size(max = 50, message = "原发票编号长度不能超过50个字符")
    private String originalInvoiceCode;

    /**
     * 对账状态(0-未对账 1-已对账 2-对账异常)
     */
    @Min(value = 0, message = "对账状态值不正确")
    @Max(value = 2, message = "对账状态值不正确")
    private Integer reconciliationStatus;

    /**
     * 对账时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime reconciliationTime;

    /**
     * 对账人ID
     */
    private Long reconcilierId;

    /**
     * 对账人姓名
     */
    @Size(max = 50, message = "对账人姓名长度不能超过50个字符")
    private String reconcilerName;

    /**
     * 归档状态(0-未归档 1-已归档)
     */
    @Min(value = 0, message = "归档状态值不正确")
    @Max(value = 1, message = "归档状态值不正确")
    private Integer archiveStatus;

    /**
     * 归档时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime archiveTime;

    /**
     * 归档人ID
     */
    private Long archiverId;

    /**
     * 归档人姓名
     */
    @Size(max = 50, message = "归档人姓名长度不能超过50个字符")
    private String archiverName;

    /**
     * 归档路径
     */
    @Size(max = 500, message = "归档路径长度不能超过500个字符")
    private String archivePath;

    /**
     * 电子发票URL
     */
    @Size(max = 500, message = "电子发票URL长度不能超过500个字符")
    private String electronicInvoiceUrl;

    /**
     * 电子发票二维码
     */
    @Size(max = 500, message = "电子发票二维码长度不能超过500个字符")
    private String electronicInvoiceQrCode;

    /**
     * 扩展字段1
     */
    @Size(max = 200, message = "扩展字段1长度不能超过200个字符")
    private String extField1;

    /**
     * 扩展字段2
     */
    @Size(max = 200, message = "扩展字段2长度不能超过200个字符")
    private String extField2;

    /**
     * 扩展字段3
     */
    @Size(max = 200, message = "扩展字段3长度不能超过200个字符")
    private String extField3;

    /**
     * 发票明细列表
     */
    private List<InvoiceDetailDTO> invoiceDetails;

    /**
     * 发票明细数据传输对象
     */
    @Data
    @Accessors(chain = true)
    public static class InvoiceDetailDTO implements Serializable {

        private static final long serialVersionUID = 1L;

        /**
         * 明细ID
         */
        private Long detailId;

        /**
         * 订单ID
         */
        private Long orderId;

        /**
         * 订单编号
         */
        private String orderCode;

        /**
         * 货物名称
         */
        @NotBlank(message = "货物名称不能为空")
        @Size(max = 200, message = "货物名称长度不能超过200个字符")
        private String goodsName;

        /**
         * 规格型号
         */
        @Size(max = 100, message = "规格型号长度不能超过100个字符")
        private String specification;

        /**
         * 单位
         */
        @Size(max = 20, message = "单位长度不能超过20个字符")
        private String unit;

        /**
         * 数量
         */
        @DecimalMin(value = "0.01", message = "数量不能小于0.01")
        private BigDecimal quantity;

        /**
         * 单价
         */
        @DecimalMin(value = "0.01", message = "单价不能小于0.01")
        private BigDecimal unitPrice;

        /**
         * 金额(不含税)
         */
        @DecimalMin(value = "0.01", message = "金额不能小于0.01")
        private BigDecimal amount;

        /**
         * 税率(%)
         */
        @DecimalMin(value = "0.0", message = "税率不能小于0%")
        @DecimalMax(value = "100.0", message = "税率不能大于100%")
        private BigDecimal taxRate;

        /**
         * 税额
         */
        @DecimalMin(value = "0.0", message = "税额不能小于0")
        private BigDecimal taxAmount;

        /**
         * 价税合计
         */
        @DecimalMin(value = "0.01", message = "价税合计不能小于0.01")
        private BigDecimal totalAmount;

        /**
         * 配送日期
         */
        @JsonFormat(pattern = "yyyy-MM-dd")
        private LocalDate deliveryDate;

        /**
         * 配送费用
         */
        @DecimalMin(value = "0.0", message = "配送费用不能小于0")
        private BigDecimal deliveryFee;

        /**
         * 备注
         */
        @Size(max = 200, message = "备注长度不能超过200个字符")
        private String remark;
    }
}